
#include <iostream>

#include "dp_trie_cidr.h"
#include "dp_trie_string2.h"
#include "dp_trie_value.h"

using namespace dp;

std::shared_ptr<dp_trie_cidr> local_create_cidr() {
    auto ret = std::make_shared<dp_trie_cidr>();
    ret->insert("10.2.196.0/24", "isp1");   // 10.2.196.0~~10.2.196.2555
    ret->insert("10.2.92.0/23", "isp2");    // 10.2.92.0~~10.2.93.255
    ret->insert("10.4.136.0/23", "isp3");   // 10.4.136.0~~10.4.137.255
    ret->insert("10.1.222.96/27", "isp4");  // 10.1.222.96~~10.1.222.127
    ret->insert("10.0.92.0/24", "isp5");    // 10.0.92.0~~10.0.92.255
    return ret;
}
int main() {
    std::string flag("字典树---字符串嵌套IP段测试---");
#define CHECK_TREE(tree, domain, ip_str, rule_str, res_str)                        \
    {                                                                              \
        std::string dn(domain), ip(ip_str), r(rule_str), result_str(res_str);      \
        std::shared_ptr<dp_trie_value> v;                                          \
        std::string rule_return;                                                   \
        std::stack<std::string> params;                                            \
        params.push(ip);                                                           \
        bool bret = tree.search(v, dn, params, &rule_return);                      \
        if (r.empty()) {                                                           \
            printf("%s%s字符串不命中测试(str=%s,ip=%s)\n",                         \
                   !bret ? "success: " : "failed: ", flag.c_str(),                 \
                   dn.c_str());                                                    \
        } else {                                                                   \
            bool bres = !result_str.empty();                                       \
            auto vv = std::dynamic_pointer_cast<dp_trie_value_string>(v);          \
            std::string tmp_res;                                                   \
            if (vv) {                                                              \
                tmp_res = vv->get_value();                                         \
            }                                                                      \
            if (result_str.empty() && NULL == vv && false == bret) {               \
                bres = true;                                                       \
                bret = true;                                                       \
            }                                                                      \
            bool tmp_bret = false;                                                 \
            if (bret && bres && 0 == result_str.compare(tmp_res) &&                \
                0 == r.compare(rule_return)) {                                     \
                tmp_bret = true;                                                   \
            }                                                                      \
            printf(                                                                \
                "%s%s字符串IP命中测试(str=%s,ip=%s,rule(%s,%s),result(%s,%" \
                "s)),%d\n",                                                        \
                tmp_bret ? "\033[32msuccess: \033[0m"                              \
                         : "\033[31;1mfailed: \033[0m",                            \
                flag.c_str(), dn.c_str(), ip.c_str(), r.c_str(),                   \
                rule_return.c_str(), result_str.c_str(), tmp_res.c_str(),          \
                bret);                                                             \
        }                                                                          \
    }

    std::string rule1("*.example.com"), rule2("test?.org"), rule3("test??.org");
    std::string rule4("xyz*"), rule5("www.example.com");
    std::string rule6("*xyz*"), rule7("abc*xyz"), rule8("abc.net"),
        rule9("test*.org");
    dp_trie_string2 trie;
    auto c = local_create_cidr();
    trie.insert(rule1, c);
    trie.insert(rule2, c);
    trie.insert(rule3, c);
    trie.insert(rule4, c);
    trie.insert(rule5, c);
    trie.insert(rule6, c);
    trie.insert(rule7, c);
    trie.insert(rule8, c);
    trie.insert(rule9, c);

    CHECK_TREE(trie, "abc.xyz..example.com", "10.2.196.0", rule6, "isp1");
    CHECK_TREE(trie, "abc.example.com", "10.2.196.254", rule1, "isp1");
    CHECK_TREE(trie, "abc.xyz..example.com", "10.3.196.1", rule6, "");
    CHECK_TREE(trie, "abc.net", "10.3.196.255", rule8, "");
    CHECK_TREE(trie, "test1.org", "10.4.136.0", rule2, "isp3");
    CHECK_TREE(trie, "test12.org", "10.1.222.96", rule3, "isp4");
    CHECK_TREE(trie, "test.org", "10.0.92.0", rule9, "isp5");
    CHECK_TREE(trie, "xyz.net", "192.68.1.1", rule4, "");
    CHECK_TREE(trie, "invalid.com", "10.0.92.0", "", "");
    CHECK_TREE(trie, "www.example.com", "10.4.135.255", rule5, "");
    CHECK_TREE(trie, "mmm.xyz.xxx", "10.0.92.255", rule6, "isp5");
    CHECK_TREE(trie, "abc.mmm.qqqq.xyz", "10.1.222.126", rule7, "isp4");
    CHECK_TREE(trie, "abc.mmm.qqqq.xyz", "10.1.222.128", rule7, "");
    return 0;
}
